package org.framework.server.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.framework.core.error.support.Errors;
import org.framework.core.util.HttpUtil;
import org.framework.core.validate.annotation.Parameter;
import org.framework.core.validate.annotation.ServiceMethod;
import org.framework.core.validate.support.param.IntegerParam;
import org.framework.core.web.handler.ServiceHandler;
import org.framework.define.Constant;
import org.framework.define.bean.entity.TblUser;
import org.framework.define.bean.entity.TblUserAccount;
import org.framework.define.bean.entity.TblUserBizAccount;
import org.framework.define.bean.entity.TblUserBlacklist;
import org.framework.define.bean.entity.TblUserInfo;
import org.framework.define.bean.entity.TblUserProgress;
import org.framework.define.bean.medium.JsonBizAccountInfo;
import org.framework.define.bean.medium.JsonIPInfo;
import org.framework.define.bean.result.Result;
import org.framework.define.bean.result.criteria.Data;
import org.framework.define.bean.result.criteria.DataResult;
import org.framework.define.error.CustomErrors;
import org.framework.define.mapper.support.UserAccountRowMapper;
import org.framework.define.param.EmailParam;
import org.framework.define.param.MobileParam;
import org.framework.define.param.PageParam;
import org.framework.define.param.SortParam;
import org.framework.define.param.TokenParam;
import org.framework.define.param.enums.BizAccountTypeEParam;
import org.framework.define.param.enums.BlackTypeEParam;
import org.framework.server.memory.Memory;
import org.framework.server.util.UserUtil;
import org.framework.server.util.dao.IServiceDao;
import org.framework.server.util.dao.sql.Logic;
import org.framework.server.util.dao.sql.support.Condition;
import org.framework.server.util.dao.sql.support.Profile;
import org.framework.server.util.dao.sql.support.QueryBuilder;
import org.framework.server.util.dao.sql.support.filter.SqlColumn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("user")
public class UserService extends ServiceHandler {
	
	@Autowired
	protected IServiceDao serviceDao;
	
	@ServiceMethod(
		value="register",
		desc="用户注册",
		params={
			@Parameter(value="login_name", min="6", max="20", desc="登录名"),
			@Parameter(value="login_pwd", min="6", max="20", desc="登陆密码"),
			@Parameter(value="real_name", max="10", desc="真实姓名"),
			@Parameter(value="email" ,type=EmailParam.class, desc="电子邮箱"),
			@Parameter(value="phone_num", type=MobileParam.class, desc="手机号码"),
			@Parameter(value="qq_num", min="5", max="15", desc="QQ号码")
		}
	)
	public Result register(HttpServletRequest request, Map<String,String> params) {
		String loginName = params.get("login_name");
		
		int count = serviceDao.count("select count(0) from tbl_user where login_name=?", new Object[]{loginName});
		if(count != 0)
			return new Result(CustomErrors.USER_ERROR_EXIST);
		
		TblUser user = new TblUser();
		user.setUserId(UserUtil.generateUserId());
		user.setLoginName(loginName);
		user.setLoginPwd(params.get("login_pwd"));
		user.setOperPwd(params.get("login_pwd"));
		user.setUserState(Constant.System.State.ACTIVE);
		
		TblUserInfo userInfo = new TblUserInfo();
		userInfo.setUserId(user.getUserId());
		userInfo.setRealName(params.get("real_name"));
		userInfo.setEmail(params.get("email"));
		userInfo.setPhoneNum(params.get("phone_num"));
		userInfo.setQqNum(params.get("qq_num"));
		userInfo.setIpAddress(HttpUtil.getRemoteAddress(request));
		JsonIPInfo ipInfo = UserUtil.getAddress(userInfo.getIpAddress());
		String address = ipInfo.getCountry()+","+ipInfo.getProvince()+","+ipInfo.getCity()+"-"+ipInfo.getIsp();
		userInfo.setAddress(address);
		userInfo.setRegTime(new Date());
		user.setTblUserInfo(userInfo);
		
		TblUserAccount userAccount = new TblUserAccount();
		userAccount.setUserId(user.getUserId());
		userAccount.setBalance(new BigDecimal(0));
		userAccount.setCoins(new BigDecimal(0));
		userAccount.setSecurityDeposit(new BigDecimal(0));
		userAccount.setCredit(0);
		user.setTblUserAccount(userAccount);
		
		TblUserProgress userProgress = new TblUserProgress();
		userProgress.setUserId(user.getUserId());
		userProgress.setTakingTaskCount(0);
		userProgress.setCompleteTaskCount(0);
		user.setTblUserProgress(userProgress);
		
		serviceDao.getMapper().save(user);
		
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="login",
		desc="用户登陆",
		params={
			@Parameter(value="login_name",min="6", max="20", desc="登录名"),
			@Parameter(value="login_pwd", min="6", max="20", desc="登陆密码"),
		}
	)
	public Result login(HttpServletRequest request, Map<String,String> params) {
		HttpSession session = request.getSession();
		
		TblUser user = serviceDao.get(
			"select * from tbl_user where login_name=? and login_pwd=?", 
			TblUser.class,
			new Object[]{params.get("login_name"), params.get("login_pwd")}
		);
		
		if(user == null)
			return new Result(CustomErrors.USER_ERROR_ACCOUNT);

		user.setLastLoginIp(HttpUtil.getRemoteAddress(request));
		user.setLastLoginTime(new Date());
		serviceDao.getMapper().update(user);
		
		session.setAttribute("user", user);
		
		return new DataResult(Errors.OK, new Data(user));
	}
	
	@ServiceMethod(
		value="logout",
		desc="用户注销",
		params={
			@Parameter(type=TokenParam.class)
		}
	)
	public Result logout(HttpServletRequest request, Map<String,String> params) {
		HttpSession session = request.getSession();
		session.removeAttribute("user");
		
		return new DataResult(Errors.OK);
	}
	
	@ServiceMethod(
		value="modifyUserInfo",
		desc="修改用户信息",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="real_name", max="10", desc="真实姓名"),
			@Parameter(value="qq_num", min="5", max="15", desc="QQ号码")
		}
	)
	public Result modifyUserInfo(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		
		TblUserInfo userinfo = serviceDao.get(TblUserInfo.class, sessionUser.getUserId());
		userinfo.setRealName(params.get("real_name"));
		userinfo.setQqNum(params.get("qq_num"));
		serviceDao.getMapper().update(userinfo);
		
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="modifyPwd",
		desc="修改登陆密码",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="old_pwd", min="6", max="20", desc="原始密码"),
			@Parameter(value="new_pwd", min="6", max="20", desc="新密码"),
		}
	)
	public Result modifyPwd(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		String oldPwd = params.get("old_pwd");
		String newPwd = params.get("new_pwd");
		
		if(!sessionUser.getLoginPwd().equals(oldPwd))
			return new Result(CustomErrors.USER_ERROR_PASSWORD);
			
		serviceDao.execute(
			"update tbl_user set login_pwd=? where user_id=?",
			new Object[]{newPwd, sessionUser.getUserId()}
		);
		sessionUser.setLoginPwd(newPwd);
		
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="modifyOperPwd",
		desc="修改操作密码",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="old_operPwd", min="6", max="20", desc="原始操作密码"),
			@Parameter(value="new_operPwd", min="6", max="20", desc="新操作密码"),
		}
	)
	public Result modifyOperPwd(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		String oldOperPwd = params.get("old_operPwd");
		String newOperPwd = params.get("new_operPwd");
		
		if(!sessionUser.getOperPwd().equals(oldOperPwd))
			return new Result(CustomErrors.USER_ERROR_OPER_PASSWORD);
			
		serviceDao.execute(
			"update tbl_user set oper_pwd=? where user_id=?",
			new Object[]{newOperPwd, sessionUser.getUserId()}
		);
		sessionUser.setOperPwd(newOperPwd);
		
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="getBlacklist",
		desc="获取黑名单列表",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(type=PageParam.class),
			@Parameter(type=SortParam.class),
			@Parameter(value="black_name", required=false, max="20", desc="筛选:名称"),
		}
	)
	public Result getBlacklist(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		
		QueryBuilder builder = new QueryBuilder(
			"select * from tbl_user_blacklist",
			new Condition(
				new SqlColumn(Logic.WHERE, "user_id").equal(sessionUser.getUserId()),
				new SqlColumn("black_user_name").contanis(params.get("black_name"))
			),
			new Profile(params)
		);
		
		DataResult result = serviceDao.queryForDataResult(builder, TblUserBlacklist.class);

		return result;
	}
	
	@ServiceMethod(
		value="addBlacklist",
		desc="添加黑名单",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="black_id", desc="被拉黑用户ID"),
			@Parameter(value="remaining_day", type=IntegerParam.class, desc="拉黑天数"),
			@Parameter(value="black_type", type=BlackTypeEParam.class, desc="拉黑类型"),
			@Parameter(value="reason", max="250", desc="拉黑原因"),
		}
	)
	public Result addBlacklist(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		String blackUserId = params.get("black_id");
		
		if(sessionUser.getUserId().equals(blackUserId))
			return new Result(CustomErrors.USER_BLACKLIST_ERROR_ADDSELF);
		
		int count = serviceDao.count(
			"select count(0) from tbl_user_blacklist where user_id=? and black_user_id=?",
			new Object[]{sessionUser.getUserId(), blackUserId}
		);
		if(count != 0)
			return new Result(CustomErrors.USER_BLACKLIST_ERROR_EXIST);
		
		Map<String, Object> blackUser = serviceDao.queryForMap(
			"select * from tbl_user where user_id=?",
			new Object[]{blackUserId}
		);
		if(blackUser == null)
			return new Result(CustomErrors.USER_ERROR_NOT_EXIST);

		
		TblUserBlacklist blacklist = new TblUserBlacklist();
		blacklist.setUserId(sessionUser.getUserId());
		blacklist.setBlackUserId(blackUserId);
		blacklist.setBlackUserName(String.valueOf(blackUser.get("login_name")));
		blacklist.setRemainingDay(Integer.parseInt(params.get("remaining_day")));
		blacklist.setBlackType(params.get("black_type"));
		blacklist.setState(Constant.System.State.Y);
		blacklist.setReason(params.get("reason"));
		blacklist.setCreateTime(new Date());
		
		serviceDao.getMapper().save(blacklist);
		
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="delBlacklist",
		desc="删除黑名单",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="id", desc="数据ID")
		}
	)
	public Result delBlacklist(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		
		serviceDao.execute(
			"delete from tbl_user_blacklist where user_id=? and id=?", 
			new Object[]{sessionUser.getUserId(), params.get("id")}
		);

		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="getBizAccountList",
		desc="获取交易账号列表",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(type=PageParam.class),
			@Parameter(type=SortParam.class),
			@Parameter(value="type", type=BizAccountTypeEParam.class, required=false, desc="交易账号类型")
		}
	)
	public Result getBizAccountList(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		
		QueryBuilder builder = new QueryBuilder(
			"select * from tbl_user_biz_account",
			new Condition(
				new SqlColumn(Logic.WHERE, "user_id").equal(sessionUser.getUserId()),
				new SqlColumn("biz_type").equal(params.get("type"))
			),
			new Profile(params)
		);
		
		DataResult result = serviceDao.queryForDataResult(builder, TblUserBizAccount.class);

		return result;
	}
	
	@ServiceMethod(
		value="addBizAccount",
		desc="添加交易账号",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="account", desc="交易账号名"),
			@Parameter(value="type", type=BizAccountTypeEParam.class, desc="交易账号类型")
		}
	)
	public Result addBizAccount(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		int type = Integer.parseInt(params.get("type"));
		String bizAct = params.get("account");
		
		//判断是否存在
		int exist = serviceDao.count(
			"select count(0) from tbl_user_biz_account where biz_type=? and biz_account=?", 
			new Object[]{type, bizAct}
		);
		if(exist > 0)
			return new Result(CustomErrors.USER_BIZACCOUNT_ERROR_EXIST);
			
		TblUserAccount account = serviceDao.get(
			"select * from tbl_user_account where user_id=?", 
			new UserAccountRowMapper(), 
			new Object[]{sessionUser.getUserId()}
		);
		//计算添加上限
		int limit = UserUtil.countRuleNum(account.getLevel(), type);
		//获取已添加个数
		int count = serviceDao.count(
			"select count(0) from tbl_user_biz_account where user_id=? and biz_type=?", 
			new Object[]{sessionUser.getUserId(), type}
		);
		
		if(count >= limit){
			return new Result(CustomErrors.USER_BIZACCOUNT_ERROR_EXCEED);
		}
		
		
			
		JsonBizAccountInfo info = null;
		try {
			info = UserUtil.accountCrawler(bizAct);
		} catch (Exception e) {
			e.printStackTrace();
			info = new JsonBizAccountInfo();
			info.setRealFlag(Constant.System.RealFlag.N);
		}
		if(info == null)
			return new Result(CustomErrors.USER_BIZACCOUNT_ERROR_NOT_EXIST_IN_WEBSITE);
		
		TblUserBizAccount bizAccount = new TblUserBizAccount();
		bizAccount.setUserId(sessionUser.getUserId());
		bizAccount.setBizAccount(bizAct);
		bizAccount.setBizType(type);
		bizAccount.setRealFlag(info.getRealFlag());
		bizAccount.setInfoUrl(info.getInfoUrl());
		bizAccount.setBizState(Constant.System.State.Y);
		bizAccount.setUseCount(0);
		bizAccount.setCreateTime(new Date());
		
		serviceDao.getMapper().save(bizAccount);
		return new Result(Errors.OK);
	}
	
	@ServiceMethod(
		value="delBuyerAccount",
		desc="删除交易买号",
		params={
			@Parameter(type=TokenParam.class),
			@Parameter(value="id", desc="交易账号ID")
		}
	)
	public Result delBuyerAccount(HttpServletRequest request, Map<String,String> params) {
		TblUser sessionUser = Memory.getSessionUser(request);
		
		serviceDao.execute(
			"delete from tbl_user_biz_account where user_id=? and id=?", 
			new Object[]{sessionUser.getUserId(), params.get("id")}
		);

		return new Result(Errors.OK);
	}
	
	public IServiceDao getServiceDao() {
		return serviceDao;
	}
	
	public void setServiceDao(IServiceDao serviceDao) {
		this.serviceDao = serviceDao;
	}
}
